package com.wei.czz.framework.common.wrapper;

import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.enums.common.dict.DictEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.utils.CacheKeyUtils;
import com.wei.czz.common.utils.RandomNumUtils;
import com.wei.czz.framework.common.entity.DictEntity;
import com.wei.czz.framework.common.handler.redis.RedisHashHandler;
import com.wei.czz.framework.common.service.DictService;
import lombok.AllArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2025-04-22 18:32:49
 * className: DictWrapper 字典操作包装类
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class DictWrapper {

    private static final Logger log = LoggerFactory.getLogger(DictWrapper.class);

    private final DictService dictService;

    private final RedisHashHandler redisHashHandler;

    private final RedissonClient redissonClient;

    /**
     * 获取字典数据操作
     * 根据字典类型，获取排序第一的可用字典数据
     * @param dictEnum 字典枚举对象
     * @return 字典数据
     */
    public DictEntity getOneDict(DictEnum dictEnum) {
        if (dictEnum.getMultiFlag()) {
            throw new CzzException("字典允许保存多次，获取数据方式错误");
        }

        String cacheKey = CacheKeyUtils.getRedisHashKey(EntityConstant.DICT);
        String valueKey = dictEnum.getStringValue();
        // 查询Redis缓存，获取字典数据
        DictEntity dict = redisHashHandler.get(cacheKey, valueKey);
        if (dict != null) {
            log.debug("从缓存中获取字典：{}", dict);
            return dict;
        }
        String lockKey = RedisConstant.LOCK + cacheKey + RedisConstant.SPLIT + valueKey + RedisConstant.SPLIT
                + RandomNumUtils.getRandomNum(3);
        RLock lock = redissonClient.getLock(lockKey);
        // 尝试加锁
        boolean bool = lock.tryLock();
        log.info("获取单个字典，尝试加锁完成。lockKey={} bool={}", lockKey, bool);
        if (!bool) {
            // 加锁
            lock.lock();
            log.info("获取单个字典，加锁成功");
        }

        try {
            if (!bool) {
                // 重复查询Redis缓存，获取字典数据
                dict = redisHashHandler.get(cacheKey, valueKey);
                if (dict != null) {
                    log.debug("double check 从缓存中获取字典：{}", dict);
                    return dict;
                }
            }

            /*
                查询数据库，获取字典
             */
            dict = dictService.getEffect(dictEnum);

            // 操作Redis缓存，保存字典缓存数据
            redisHashHandler.put(cacheKey, valueKey, dict);

            return dict;
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }
        }
    }

    /**
     * 获取字典数据操作
     * 根据字典类型，获取对应的字典数据
     * @param dictEnum 字典枚举对象
     * @return 字典数据
     */
    public List<DictEntity> getDictList(DictEnum dictEnum) {
        if (!dictEnum.getMultiFlag()) {
            throw new CzzException("字典只能保存一次，获取数据方式错误");
        }
        String cacheKey = CacheKeyUtils.getRedisHashKey(EntityConstant.DICT);
        String valueKey = dictEnum.getStringValue();

        // 查询Redis缓存，获取字典数据
        List<DictEntity> dictList = redisHashHandler.get(cacheKey, valueKey);
        if (!CollectionUtils.isEmpty(dictList)) {
            log.debug("从redis缓存中得到字典列表。{}", dictList);
            return dictList;
        }

        String lockKey = RedisConstant.LOCK + cacheKey + RedisConstant.SPLIT + valueKey + RedisConstant.SPLIT
                + RandomNumUtils.getRandomNum(3);
        RLock lock = redissonClient.getLock(lockKey);
        // 尝试加锁
        boolean bool = lock.tryLock();
        log.info("获取字典列表，尝试加锁完成。lockKey={} bool={}", lockKey, bool);
        if (!bool) {
            // 加锁
            lock.lock();
            log.info("获取字典列表，加锁成功");
        }

        try {
            if (!bool) {
                // 重复查询Redis缓存，获取字典数据
                dictList = redisHashHandler.get(cacheKey, valueKey);
                if (!CollectionUtils.isEmpty(dictList)) {
                    log.debug("double check 从redis缓存中得到字典列表。{}", dictList);
                    return dictList;
                }
            }

            /*
                查询数据库，获取字典列表
             */
            dictList = dictService.findEffectList(dictEnum);
            if (dictList.isEmpty()) {
                throw new CzzException(dictEnum.getName() + "没有可用配置，请务必及时处理");
            }

            // 添加缓存
            redisHashHandler.put(cacheKey, valueKey, dictList);

            return dictList;
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }
        }
    }

}
